#pragma once

#include <iostream>
#include <memory>
#include <functional>
#include "Epoller.hpp"
#include "InetAddr.hpp"
#include "Log.hpp"
#include "Sock.hpp"
#include "Log.hpp"
#include "Connection.hpp"
#include "Protocol.hpp"
#include "Reactor.hpp"



using namespace std;

using func_t = function<string(string &)>;

class IOService : public Connection
{
   static const int size = 1024;

private:
   func_t _message;

public:
   IOService(int sockfd)
   {
      SetNoBlack(sockfd);
      // 继承关系，connection有客户端的addr，缓冲区
      SetSockfd(sockfd);
      SetEvents(EPOLLIN | EPOLLET);
   }

   virtual void Sender() override
   {
      while (true)
      {
         ssize_t n = send(Sockfd(), outstring().c_str(), outstring().size(), 0);
         if (n > 0)
         {
            DisCardOutString(n);
         }
         else if (n == 0)
         {
            break;
         }
         else
         {
            if (errno == EAGAIN || errno == EWOULDBLOCK)
            {
               // 发送缓冲区写满了，下次再来
               break;
            }
            else if (errno = EINTR)
            {
               // 信号打断，继续
               continue;
            }
            else
            {
               Excepter();
               return;
            }
         }
         // 一种：outbuffer empty
         // 一种：发送缓冲区被写满了 && outbuffer没有empty，写条件不满足，使能sockfd在epoll中的事件
         if (!IsOutBufferEmpty())
         {
            // 修改对sockfd的事件关心！-- 开启对写事件关心
            // 按需设置！
            GetOwner()->EnableRW(Sockfd(), true, true);
         }
         else
         {
            GetOwner()->EnableRW(Sockfd(), true, false);
         }
      }
   }

   virtual void Recver() override
    {
        // UpdateTime();
        // 1. 读取所有数据
        while (true) // ET模式
        {
            char buffer[size];
            ssize_t s = recv(Sockfd(), buffer, sizeof(buffer) - 1, 0); // 非阻塞
            if (s > 0)
            {
                buffer[s] = 0;
                // 读取成功了
                Append_in(buffer);
            }
            if (s == 0)
            {
                // 对端关闭连接
                Excepter();
                return;
            }
            else
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break;
                }
                else if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    // 发生错误了
                    Excepter();
                    return;
                }
            }
        }

        // 走到下面，我一定把本轮数据读取完毕了
        cout << "outbuffer: \n"
                  << InBuffer() << std::endl;
        // 你能确保你读到的消息，就是一个完整的报文吗？？不能！！！
        // 我们怎么知道，读到了完整的请求呢？？协议！！！
        std::string result;
        if (_message)
            result = _message(InBuffer()); // 
        // 添加应答信息
        Append_Out(result);

        // 如何处理写的问题, outbuffer 发送给对方的问题！
        if (!IsOutBufferEmpty())
        {
            //方案一: Sender(); // 直接发送, 推荐做法
            //方案二: 使能Writeable即可.
            GetOwner()->EnableRW(Sockfd(), true, true);
        }
    }

    virtual void Excepter() override
    {
         LOG(Log_Level::INFO)<<"客户端连接可能结束，进行异常处理: " << Sockfd();
         GetOwner()->DelConnection(Sockfd());
    }

    void Register_Message(func_t message)
    {
        _message = message;
    }

   ~IOService(){}
};